home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / KPlib 1.3.5 / sample_progs / deps.cxx < prev    next >
C/C++ Source or Header  |  1995-12-17  |  7KB  |  193 lines

  1. /*
  2.     This program accepts a list of C or C++ source files for a project
  3.     and outputs a dependency list suitable for a Makefile.  It
  4.     recursively parses the include files to insure that all
  5.     dependencies are noted.  Relative and absolute pathnames for both
  6.     source and include files are correctly handled.  Only include lines
  7.     that start with `#include "' are looked at.  Commented-out include
  8.     lines are not ignored.
  9.  
  10.     Only dependency lists for the object files corresponding to the
  11.     source files are generated.  It is the responsibility of the
  12.     programmer to supply the dependency lists for the desired
  13.     executables and to define $(CC) and $(CFLAGS).  If a file called
  14.     `.makeheader' exists in the project directory, the contents of this
  15.     file will be prepended to the output of this program.  Thus, if the
  16.     user places user-defined dependencies in this file, the command
  17.  
  18.             deps *.c > Makefile
  19.  
  20.     will correctly create a complete Makefile for a C project.
  21.  
  22.     Written by Keith Pomakis on October 10, 1994.  Public Domain.
  23. */
  24.  
  25. #include <iostream.h>
  26. #include <fstream.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include "../KPbasic.h"
  30. #include "../KPList.h"
  31. #include "../KPString.h"
  32. #include "../KPSet.h"
  33.  
  34. // Explicit instantiations of required templates.  This is necessary for
  35. // g++ 2.6.x in conjunction with the "-fno-implicit-templates" option, but
  36. // may not be necessary in the future.
  37.  
  38. template class KPSet<KPString>;
  39. template class KPList<KPString>;
  40. template class KPComparableList<KPString>;
  41. template class KPSortableList<KPString>;
  42. template class KPReadOnlyIterator<KPString>;
  43. template class KPIterator<KPString>;
  44.  
  45. KPString progname;
  46.  
  47. const char *const headerfile = ".makeheader";
  48.  
  49. /****************************************************************************/
  50.  
  51. static inline KPString base(const KPString &string)
  52. { return string.tokens('/').tail(); }
  53.  
  54. static inline KPString path(const KPString &string)
  55. { return string.substr(0, string.length() - base(string).length()); }
  56.  
  57. static inline bool is_relative(const KPString &string)
  58. { return string.is_empty() || string[0] != '/'; }
  59.  
  60. static inline KPString root(const KPString &string)
  61. { return string.tokens('.').head(); }
  62.  
  63. static void process_header();
  64. static void process_source(const KPString &sourcename);
  65. static bool process_file(const KPString &filename, KPSet<KPString> &includes,
  66.                          KPString pathname);
  67.  
  68. /****************************************************************************/
  69.  
  70. int
  71. main(int argc, char *argv[])
  72. {
  73.     progname = base(argv[0]);
  74.  
  75.     if (argc < 2) {
  76.         cerr << "Usage: " << progname << " -help\n"
  77.              << "       " << progname << " <sourcefile> ...\n";
  78.         exit(EXIT_FAILURE);
  79.     }
  80.  
  81.     if (strncmp(argv[1], "-h", 2) == 0) {
  82.         cout <<
  83.         "This program accepts a list of C or C++ source files for a project\n"
  84.         "and outputs a dependency list suitable for a Makefile.  It\n"
  85.         "recursively parses the include files to insure that all\n"
  86.         "dependencies are noted.  Relative and absolute pathnames for both\n"
  87.         "source and include files are correctly handled.  Only include lines\n"
  88.         "that start with `#include \042' are looked at.  Commented-out\n"
  89.         "include lines are not ignored.\n\n"
  90.         "Only dependency lists for the object files corresponding to the\n"
  91.         "source files are generated.  It is the responsibility of the\n"
  92.         "programmer to supply the dependency lists for the desired\n"
  93.         "executables and to define $(CC) and $(CFLAGS).  If a file called\n"
  94.         "`.makeheader' exists in the project directory, the contents of this\n"
  95.         "file will be prepended to the output of this program.  Thus, if the\n"
  96.         "user places user-defined dependencies in this file, the command\n\n"
  97.         "        " << progname << " *.c > Makefile\n\n"
  98.         "will correctly create a complete Makefile for a C project.\n\n"
  99.         "Written by Keith Pomakis on October 10, 1994.  Public Domain.\n";
  100.         exit(EXIT_SUCCESS);
  101.     }
  102.  
  103.     process_header();
  104.  
  105.     time_t current_time = time(NULL);
  106.     cout << "\n###########################################################\n";
  107.     cout << "#\n";
  108.     cout << "#  File dependencies generated by \042" << progname << "\042.\n";
  109.     cout << "#  " << ctime(¤t_time);
  110.     cout << "#\n";
  111.     cout << "###########################################################\n\n";
  112.  
  113.     for (int i=1; i<argc; i++)
  114.         process_source(argv[i]);
  115.  
  116.     return 0;
  117. }
  118.  
  119. /****************************************************************************/
  120.  
  121. static void
  122. process_header()
  123. {
  124.     ifstream stream(headerfile, ios::in);
  125.     if (!stream) return;
  126.  
  127.     KPString line;
  128.  
  129.     while (!stream.eof()) {
  130.         line.read_line(stream);
  131.         if (!stream.eof()) cout << line << '\n';
  132.     }
  133. }
  134.  
  135. /****************************************************************************/
  136.  
  137. static void
  138. process_source(const KPString &sourcename)
  139. {
  140.     KPSet<KPString> includes = sourcename;
  141.  
  142.     cout << root(base(sourcename)) << ".o: \\\n";
  143.  
  144.     if (process_file(sourcename, includes, path(sourcename))) {
  145.         KPReadOnlyIterator<KPString> iter(includes.list());
  146.         FOREACH(iter) {
  147.             cout << "    " << *iter;
  148.             if (!iter.at_end()) cout << " \\";
  149.             cout << '\n';
  150.         }
  151.         cout << "\t$(CC) $(CFLAGS) -c " << sourcename << "\n\n";
  152.     }
  153. }
  154.  
  155. /****************************************************************************/
  156.  
  157. static bool
  158. process_file(const KPString &filename, KPSet<KPString> &includes,
  159.                    KPString pathname)
  160. {
  161.     ifstream stream(filename, ios::in);
  162.     if (!stream) {
  163.         cerr << progname << ": error opening file \042" << filename << "\042\n";
  164.         return false;
  165.     }
  166.  
  167.     KPString line;
  168.  
  169.     while (!stream.eof()) {
  170.         line.read_line(stream);
  171.         if (line.length() > 11 && memcmp(line, "#include \042", 10) == 0) {
  172.             const int second_quote = line.index_of('\042', 10);
  173.             if (second_quote < 0 || second_quote == 10) {
  174.                 cerr << progname << ": error in file \042" << filename
  175.                      << "\042 - bad include line:\n" << line << '\n';
  176.                 return false;
  177.             }
  178.             KPString new_include = line.substr(10, second_quote-10);
  179.             if (is_relative(new_include)) new_include = pathname + new_include;
  180.             if (!includes.contains(new_include)) {
  181.                 includes += new_include;
  182.                 if (!process_file(new_include, includes, path(new_include)))
  183.                     return false;
  184.             }
  185.         }
  186.     }
  187.  
  188.     return true;
  189. }
  190.  
  191. /****************************************************************************/
  192.  
  193.